package com.yd.obtainhashsign

import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.graphics.drawable.Drawable
import android.util.Base64
import android.util.Log
import java.io.ByteArrayInputStream
import java.io.Serializable
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.util.*


object AppSigningUtil {


    var TAG = "AppSigning"

    const val MD5 = "MD5"
    const val SHA1 = "SHA1"
    const val SHA256 = "SHA256"

    data class AppInfo(
        var appName: String = "",
        var packageName: String = "",
        var versionName: String = "",
        var versionCode: Int = 0,
        var appIcon: Drawable? = null
    ) : Serializable

    /**
     * 返回一个签名的对应类型的字符串
     *
     * @param context
     * @param packageName
     * @param type
     * @return
     */
    fun getSingInfo(context: Context, packageName: String, type: String): String? {
        var tmp: String? = "error!"
        try {
            val signs = getSignatures(context, packageName)
            Log.e(TAG, "signs =  " + Arrays.asList(signs))
            val sig = signs!![0]
            if (MD5 == type) {
                tmp = getSignatureString(sig, MD5)
            } else if (SHA1 == type) {
                tmp = getSignatureString(sig, SHA1)
            } else if (SHA256 == type) {
                tmp = getSignatureString(sig, SHA256)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return tmp
    }

    /**
     * 返回对应包的签名信息
     *
     * @param context
     * @param packageName
     * @return
     */
    fun getSignatures(context: Context, packageName: String?): Array<Signature>? {
        var packageInfo: PackageInfo? = null
        try {
            packageInfo =
                context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
            return packageInfo.signatures
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 获取相应的类型的字符串（把签名的byte[]信息转换成16进制）
     *
     * @param sig
     * @param type
     * @return
     */
    fun getSignatureString(sig: Signature, type: String?): String? {
        val hexBytes = sig.toByteArray()
        var fingerprint = "error!"
        try {
            val buffer = StringBuffer()
            val digest = MessageDigest.getInstance(type)
            if (digest != null) {
                digest.reset()
                digest.update(hexBytes)
                val byteArray = digest.digest()
                for (i in byteArray.indices) {
                    if (Integer.toHexString(0xFF and byteArray[i].toInt()).length == 1) {
                        buffer.append("0").append(
                            Integer.toHexString(
                                0xFF and byteArray[i]
                                    .toInt()
                            )
                        ) //补0，转换成16进制
                    } else {
                        buffer.append(Integer.toHexString(0xFF and byteArray[i].toInt())) //转换成16进制
                    }
                    buffer.append(":")
                }
                val result = buffer.substring(0, buffer.length - 1)
                fingerprint = result.toUpperCase() //转换成大写
            }
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
        return fingerprint
    }


    fun getFaceBookHash(context: Context, packageName: String): String {
        var result = "getFaceBookHash Error Happen!"
        try {
            val info =
                context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
            if (info != null) {
                for (signature in info.signatures) {
                    val md = MessageDigest.getInstance("SHA")
                    md.update(signature.toByteArray());
                    val key = Base64.encodeToString(md.digest(), Base64.DEFAULT)
                    result = key
                }
            }
        } catch (e: PackageManager.NameNotFoundException) {
            result = e.message ?: ""
        }
        return result
    }

    /**
     * 将获取到得编码进行16进制转换
     *
     * @param arr
     * @return
     */
    fun byte2HexFormatted(arr: ByteArray): String? {
        val str = StringBuilder(arr.size * 2)
        for (i in arr.indices) {
            var h = Integer.toHexString(arr[i].toInt())
            val l = h.length
            if (l == 1) h = "0$h"
            if (l > 2) h = h.substring(l - 2, l)
            str.append(h.toUpperCase())
            if (i < arr.size - 1) str.append(':')
        }
        return str.toString()
    }


    fun getMd5(context: Context, packageName: String): String {
        var result = "getMd5 Error Happen!"
        val packageManager: PackageManager = context.getPackageManager()
        //请注意需要PackageManager.GET_SIGNATURES 这个flag
        val packageInfo: PackageInfo = packageManager.getPackageInfo(
            context.getPackageName(),
            PackageManager.GET_SIGNATURES
        )
        val signs: Array<Signature> = packageInfo.signatures
        val sign: Signature = signs[0]
        // X509证书，X.509是一种非常通用的证书格式
        val certFactory: CertificateFactory = CertificateFactory.getInstance("X.509")
        val cert: X509Certificate = certFactory
            .generateCertificate(ByteArrayInputStream(sign.toByteArray())) as X509Certificate
        // md5
        val md = MessageDigest.getInstance("MD5")
        // 获得公钥
        val key = md.digest(cert.getEncoded());
        result = byte2HexFormatted(key) ?: result
        return result
    }

    fun getPackages(context: Context): List<AppInfo> {
        // 获取已经安装的所有应用, PackageInfo　系统类，包含应用信息
        var mData = mutableListOf<AppInfo>()
        val pm = context.packageManager
        val packages: List<PackageInfo> = pm.getInstalledPackages(0)
        for (i in packages.indices) {
            val packageInfo = packages[i]
            if (packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0) { //非系统应用
                // AppInfo 自定义类，包含应用信息
                val appInfo = AppInfo()
                appInfo.appName = packageInfo.applicationInfo.loadLabel(pm).toString() //获取应用名称
                appInfo.packageName = packageInfo.packageName //获取应用包名，可用于卸载和启动应用
                appInfo.versionName = packageInfo.versionName //获取应用版本名
                appInfo.versionCode = packageInfo.versionCode //获取应用版本号
                appInfo.appIcon = packageInfo.applicationInfo.loadIcon(pm) //获取应用图标
                mData.add(appInfo)
            } else { // 系统应用
            }
        }
        return mData
    }
}